﻿#region License
/* ---------------------------------------------------------------- *
 *
 * This file is part of the Xcoordination Application Space
 * ("XcoAppSpace") http://www.xcoordination.com
 *
 * Copyright (C) 2009 Xcoordination http://www.xcoordination.com
 *
 * XcoAppSpace is free software; you can redistribute it and/or
 * modify it under the terms of version 2 of the GNU General
 * Public License as published by the Free Software Foundation.
 *
 * XcoAppSpace is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see http://www.gnu.org/licenses/
 * or write to the Free Software Foundation, Inc., 51 Franklin
 * Street, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 * ---------------------------------------------------------------- */
#endregion

using System;
using System.IO;
using System.Threading;
using XcoAppSpaces.Contracts.Transport;
using XcoAppSpaces.Contracts.Logging;
using System.Messaging;

namespace XcoAppSpaces.Transport.MSMQ
{
	internal class MSMQServer : IDisposable
	{
#pragma warning disable 219
		private readonly IXcoLogger log;
#pragma warning restore 219

        private readonly MessageQueue msgQueue;
        
		private bool running;
		private readonly XcoMSMQTransportService commService;
	    private TransferHelper transferHelper;
        public string QueuePath
        {
            get
            {
                return msgQueue.Path;
            }
        }

		public MSMQServer(string msgQueueName, XcoMSMQTransportService commService, IXcoLogger log)
		{
            this.commService = commService;
			this.log = log;
            transferHelper = new TransferHelper();

            if (!MessageQueue.Exists(msgQueueName))
                MessageQueue.Create(msgQueueName, true);
                       
            msgQueue = new MessageQueue(msgQueueName);

            msgQueue.ReceiveCompleted += msgQueue_ReceiveCompleted;
            running = true; 
            msgQueue.BeginReceive();
		}

        void msgQueue_ReceiveCompleted(object source, ReceiveCompletedEventArgs asyncResult)
        {
            try
            {
                MessageQueue queue = (MessageQueue)source;
                
                // End the asynchronous receive operation.
                Message qMsg = queue.EndReceive(asyncResult.AsyncResult);

                ThreadPool.QueueUserWorkItem(StartReceive, qMsg);

                if (running)
                {
                    msgQueue.BeginReceive();
                }
            }
            catch (Exception ex)
            {
               log.Warn(ex.Message);
            }
        }

        private void StartReceive(object qMsgObj)
        {
        	string remoteAddress;
            XcoMessage msg = transferHelper.Convert(new BinaryReader(((Message)qMsgObj).BodyStream), out remoteAddress);
            if (msg != null)
            {
                commService.RaiseMessageReceivedEvent(msg, remoteAddress);
            }
        }

		public void Stop()
		{
			running = false;
			if (msgQueue != null)
			{               
                msgQueue.Close();
			}
		}

		public void Dispose()
		{
			Stop();
		}
	}
}
